package com.txby.dplus.common.utils.util;

import java.util.Calendar;
import java.util.Date;

import org.apache.commons.lang.time.DateFormatUtils;

//import org.apache.commons.lang3.time.DateFormatUtils;

/**
 * 日期操作类
 * 
 * @author Administrator
 *
 */
public class DateUtils {

    /**
     * yyyyMMdd
     */
    public static final String YYYYMMDD_8 = "yyyyMMdd";
    /**
     * yyyy-MM-dd
     */
    public static final String YYYYMMDD_10 = "yyyy-MM-dd";
    /**
     * yyyy-MM-dd HH:mm
     */
    public static final String YYYYMMDDHHMM_16 = "yyyy-MM-dd HH:mm";
    /**
     * yyyy-MM-dd HH:mm:ss
     */
    public static final String YYYYMMDDHHMMSS_19 = "yyyy-MM-dd HH:mm:ss";

    private static final String DEFAULT_PATTERN = YYYYMMDD_10;

    /**
     * 日期转换字符串，默认格式为yyyy-MM-dd
     * 
     * @param date
     * @return
     */
    public static String format(Date date) {
        return format(date, DEFAULT_PATTERN);
    }

    /**
     * 日期转换字符串，默认格式为yyyy-MM-dd
     * 
     * @param millis
     * @return
     */
    public static String format(long millis) {
        return format(millis, DEFAULT_PATTERN);
    }

    /**
     * 日期转换字符串，默认格式为yyyy-MM-dd
     * 
     * @param calendar
     * @return
     */
    public static String format(Calendar calendar) {
        return format(calendar, DEFAULT_PATTERN);
    }

    /**
     * 用给定的格式转换日期为字符串
     * 
     * @param date
     * @param pattern
     * @return
     */
    public static String format(Date date, String pattern) {
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 用给定的格式转换日期为字符串
     * 
     * @param millis
     * @param pattern
     * @return
     */
    public static String format(long millis, String pattern) {
        return DateFormatUtils.format(millis, pattern);
    }

    /**
     * 用给定的格式转换日期为字符串
     * 
     * @param calendar
     * @param pattern
     * @return
     */
    public static String format(Calendar calendar, String pattern) {
        return DateFormatUtils.format(calendar, pattern);
    }

    /**
     * 字符串转日期，默认格式为yyyy-MM-dd
     * 
     * @param strDate
     * @return
     */
    public static Date parseDate(String strDate) {
        return parseDate(strDate, DEFAULT_PATTERN);
    }

    /**
     * 用给定的格式转换字符串为日期
     * 
     * @param strDate
     * @param pattern
     * @return
     */
    public static Date parseDate(String strDate, String pattern) {
        Date result = null;
        try {
            result = DateUtils.parseDate(strDate, pattern);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
        return result;
    }

    /*-----------------下面所有的compare方法返回1, 0, -1 三种值-----------------*/
    /**
     * 比较年份
     * 
     * @param dateOne
     * @param dateTwo
     * @return 1：大于<br/>
     *         0：相等<br/>
     *         -1：小于<br/>
     */
    public static int compareYear(Date dateOne, Date dateTwo) {
        return compareField(dateOne, dateTwo, Calendar.YEAR);
    }

    /**
     * 比较从year到month字段
     * 
     * @param dateOne
     * @param dateTwo
     * @return 1：大于<br/>
     *         0：相等<br/>
     *         -1：小于<br/>
     */
    public static int compareYearToMonth(Date dateOne, Date dateTwo) {
        int result = compareField(dateOne, dateTwo, Calendar.YEAR);
        if (result != 0) {
            return result;
        } else {
            return compareField(dateOne, dateTwo, Calendar.MONTH);
        }
    }

    /**
     * 比较从year到day字段
     * 
     * @param dateOne
     * @param dateTwo
     * @return 1：大于<br/>
     *         0：相等<br/>
     *         -1：小于<br/>
     */
    public static int compareYearToDay(Date dateOne, Date dateTwo) {
        int result = compareField(dateOne, dateTwo, Calendar.YEAR);
        if (result != 0) {
            return result;
        } else {
            return compareField(dateOne, dateTwo, Calendar.DAY_OF_YEAR);
        }
    }

    /**
     * 比较从year到hour字段
     * 
     * @param dateOne
     * @param dateTwo
     * @return 1：大于<br/>
     *         0：相等<br/>
     *         -1：小于<br/>
     */
    public static int compareYearToHour(Date dateOne, Date dateTwo) {
        int result = compareField(dateOne, dateTwo, Calendar.YEAR);
        if (result != 0) {
            return result;
        } else {
            result = compareField(dateOne, dateTwo, Calendar.DAY_OF_YEAR);
            if (result != 0) {
                return result;
            } else {
                return compareField(dateOne, dateTwo, Calendar.HOUR_OF_DAY);
            }
        }
    }

    /**
     * 比较从year到minutes字段
     * 
     * @param dateOne
     * @param dateTwo
     * @return 1：大于<br/>
     *         0：相等<br/>
     *         -1：小于<br/>
     */
    public static int compareYearToMinutes(Date dateOne, Date dateTwo) {
        int result = compareField(dateOne, dateTwo, Calendar.YEAR);
        if (result != 0) {
            return result;
        }
        result = compareField(dateOne, dateTwo, Calendar.DAY_OF_YEAR);
        if (result != 0) {
            return result;
        }
        result = compareField(dateOne, dateTwo, Calendar.HOUR_OF_DAY);
        if (result != 0) {
            return result;
        }
        return compareField(dateOne, dateTwo, Calendar.MINUTE);
    }

    /**
     * 比较从year到second字段
     * 
     * @param dateOne
     * @param dateTwo
     * @return 1：大于<br/>
     *         0：相等<br/>
     *         -1：小于<br/>
     */
    public static int compareYearToSeconds(Date dateOne, Date dateTwo) {
        int result = compareField(dateOne, dateTwo, Calendar.YEAR);
        if (result != 0) {
            return result;
        }
        result = compareField(dateOne, dateTwo, Calendar.DAY_OF_YEAR);
        if (result != 0) {
            return result;
        }
        result = compareField(dateOne, dateTwo, Calendar.HOUR_OF_DAY);
        if (result != 0) {
            return result;
        }
        result = compareField(dateOne, dateTwo, Calendar.MINUTE);
        if (result != 0) {
            return result;
        }
        return compareField(dateOne, dateTwo, Calendar.SECOND);
    }

    /**
     * 比较两个日期是否完全相同
     * 
     * @param dateOne
     * @param dateTwo
     * @return 1：大于<br/>
     *         0：相等<br/>
     *         -1：小于<br/>
     */
    public static int compareDate(Date dateOne, Date dateTwo) {
        if (dateOne == null) {
            throw new IllegalArgumentException("The dateOne must not be null");
        }
        if (dateTwo == null) {
            throw new IllegalArgumentException("The dateTwo must not be null");
        }
        long result = dateOne.getTime() - dateTwo.getTime();
        if (result > 0) {
            return 1;
        }
        if (result < 0) {
            return -1;
        }
        return 0;
    }

    private static int compareField(Date dateOne, Date dateTwo, int calendarField) {
        if (dateOne == null) {
            throw new IllegalArgumentException("The dateOne must not be null");
        }
        if (dateTwo == null) {
            throw new IllegalArgumentException("The dateTwo must not be null");
        }
        Calendar compareCalendarOne = Calendar.getInstance();
        compareCalendarOne.setTime(dateOne);
        Calendar compareCalendarTwo = Calendar.getInstance();
        compareCalendarTwo.setTime(dateTwo);
        int result = compareCalendarOne.get(calendarField) - compareCalendarTwo.get(calendarField);
        if (result > 0) {
            return 1;
        }
        if (result < 0) {
            return -1;
        }
        return 0;
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of years to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addYears(Date date, int amount) {
        return add(date, Calendar.YEAR, amount);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of months to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addMonths(Date date, int amount) {
        return add(date, Calendar.MONTH, amount);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of weeks to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addWeeks(Date date, int amount) {
        return add(date, Calendar.WEEK_OF_YEAR, amount);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of days to a date returning a new object. The original date
     * object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addDays(Date date, int amount) {
        return add(date, Calendar.DAY_OF_MONTH, amount);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of hours to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addHours(Date date, int amount) {
        return add(date, Calendar.HOUR_OF_DAY, amount);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of minutes to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addMinutes(Date date, int amount) {
        return add(date, Calendar.MINUTE, amount);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of seconds to a date returning a new object. The original
     * date object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addSeconds(Date date, int amount) {
        return add(date, Calendar.SECOND, amount);
    }

    // -----------------------------------------------------------------------
    /**
     * Adds a number of milliseconds to a date returning a new object. The
     * original date object is unchanged.
     *
     * @param date
     *            the date, not null
     * @param amount
     *            the amount to add, may be negative
     * @return the new date object with the amount added
     * @throws IllegalArgumentException
     *             if the date is null
     */
    public static Date addMilliseconds(Date date, int amount) {
        return add(date, Calendar.MILLISECOND, amount);
    }

    private static Date add(Date date, int calendarField, int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }

    /**
     * 判断日期是否在开始日期和结束日期之间
     * 
     * @param startTime
     *            开始日期
     * @param endTime
     *            结束日期
     * @param toJudgeTime
     *            待判断日期
     * @return boolean 如果待判断日期在开始日期和结束日期之间，则返回true;否则返回false。
     */
    public static boolean checkBetween(Date startTime, Date endTime, Date toJudgeTime) {
        return startTime.before(toJudgeTime) && endTime.after(toJudgeTime);
    }

    /**
     * 判断两个日期段是否有重叠
     * 
     * @param start1
     *            第一日期段的开始日期
     * @param end1
     *            第一日期段的结束日期
     * @param start2
     *            第二日期段的开始日期
     * @param end2
     *            第二日期段的结束日期
     * @return boolean 两个日期段无重叠，则返回true;否则返回false。
     */
    public static boolean checkOverlapped(Date start1, Date end1, Date start2, Date end2) {
        if (start1.before(end1) && start2.before(end2)) {
            if (end1.before(start2) || end2.before(start1)) {
                return false;
            } else {
                return true;
            }
        }
        return false;
    }

    /**
     * 计算两个日期相差天数
     * 
     * @param date1
     *            日期一
     * @param date2
     *            日期二
     * @return long 间隔天数
     */
    public static long calculateDiffDays(Date date1, Date date2) {
        long diff = date1.getTime() - date2.getTime();
        long days = diff % (1000 * 60 * 60 * 24) == 0 ? diff / (1000 * 60 * 60 * 24) : diff / (1000 * 60 * 60 * 24) + 1;
        return days;
    }

}
